﻿using HDS.Admin.Api.ViewModels;
using HDS.Admin.Api.ViewModels.Auth;
using HDS.IService.Sys;
using HDS.Model;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Cors;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
using Microsoft.IdentityModel.Tokens;
using System;
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using System.Text;
using System.Threading.Tasks;
using System.Linq;
using System.Collections.Generic;
using HDS.Model.Entity.Sys;

namespace HDS.Admin.Api.Controllers
{
    [Route("[controller]/[action]")]
    [ApiController]
    [EnableCors]
    public class AuthController : Controller
    {
        public IConfiguration Configuration { get; }
        private readonly ILogger<AuthController> _logger;
        private readonly ISysUserService _isysUserService;

        public AuthController(IConfiguration configuration, ILogger<AuthController> logger, ISysUserService isysUserService)
        {
            _logger = logger;
            _isysUserService = isysUserService;
            Configuration = configuration;
        }

        [AllowAnonymous]
        public ResultData<string> Index()
        {
            return new ResultData<string> { Success = true };
        }

        [HttpGet]
        [HttpPost]
        [AllowAnonymous]
        public async Task<ResultData<TokenInfo>> Login([FromBody] LoginDto loginDto)
        {
            var user = await _isysUserService.Get(loginDto.Email, loginDto.Password);
            if (user == null || !user.UserStatus)
                return new ResultData<TokenInfo> { Success = false, Code = ErrorCode.DataValidationFailed, Message = "用户名或密码错误" };

            var claims = new[] {
                    new Claim(ClaimTypes.Sid, user.UserId.ToString()),
                    new Claim(ClaimTypes.Name, user.UserName),
                    new Claim(ClaimTypes.Email, user.UserEmail)
                };

            var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(Configuration.GetSection("JWT")["IssuerSigningKey"]));
            var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);

            var expireAt = Convert.ToInt32(Configuration.GetSection("JWT")["Expires"]);
            var securityToken = new JwtSecurityToken(
                issuer: Configuration.GetSection("JWT")["ValidIssuer"],
                audience: Configuration.GetSection("JWT")["ValidAudience"],
                claims: claims,
                expires: DateTime.Now.AddMinutes(expireAt),
                signingCredentials: creds);

            var token = new JwtSecurityTokenHandler().WriteToken(securityToken);

            return new ResultData<TokenInfo>
            {
                Success = true,
                Data = new TokenInfo
                {
                    Token = token,
                    User = new Model.Entity.Sys.SysUser
                    {
                        UserEmail = user.UserEmail,
                        UserId = user.UserId,
                        UserName = user.UserName,
                        UserPhone = user.UserPhone
                    },
                    expireAt = expireAt
                }
            };
        }

        [Authorize]
        public async Task<ResultData<RouteConfig[]>> Routes()
        {
            var userId = Convert.ToInt32(User.FindFirstValue(ClaimTypes.Sid));
            var funList = await _isysUserService.GetFuns(userId);
            var routeConfigs = new RouteConfig
            {
                Router = "root",
                Children = new List<RouteConfig>()
            };

            routeConfigs.Children.Add(new RouteConfig { Router = "dashboard" });
            routeConfigs.Children.Add(new RouteConfig { Router = "mysettings" });
            var pFunList = funList.Where(e => e.FunPid == 0 && e.FunType == 1 && !string.IsNullOrEmpty(e.FunRouter)).OrderBy(e => e.FunOrderby);
            foreach (var pfun in pFunList)
            {
                routeConfigs.Children.Add(GetRouter(funList, pfun));
            }

            return new ResultData<RouteConfig[]>
            {
                Success = true,
                Data = new RouteConfig[] { routeConfigs }
            };
        }

        private RouteConfig GetRouter(List<SysFun> allFunList, SysFun pFun)
        {
            var routeConfig = new RouteConfig
            {
                Router = pFun.FunRouter
            };
            var children = allFunList.Where(e => e.FunPid == pFun.FunId && !string.IsNullOrEmpty(e.FunRouter) && e.FunType < 4).OrderBy(e => e.FunOrderby).ToList();
            if (children.Any())
            {
                routeConfig.Children = new List<RouteConfig>();
                foreach (var child in children)
                {
                    routeConfig.Children.Add(GetRouter(allFunList, child));
                }
            }

            return routeConfig;
        }
    }
}
